home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
tools
/
init.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-15
|
13KB
|
407 lines
/* This process is the father (mother) of all Minix user processes. When
* Minix comes up, this is process number 2, and has a pid of 1. It
* executes the /etc/rc shell file, and then reads the /etc/ttys file to
* determine which terminals need a login process. The ttys file consists
* of three-field lines as follows:
* abc
* where
* a = 0 (line disabled = no shell), 1 (enabled = shell started)
* 2 (enabled through a GETTY)
* b = a-r defines UART paramers (baud, bits, parity), 0 for console
* c = line number or line name
*
* The letters a-r correspond to the 18 entries of the uart table below.
* For example, 'a' is 110 baud, 8 bits, no parity; 'b' is 300 baud, 8
* bits, no parity; 'j' is 2400 baud, 7 bits, even parity; etc. If the
* third field is a digit, then the terminal device will be /dev/tty{c},
* otherwise it will be /dev/{c}. Note that since login cheats in
* determining the slot number, entries in /etc/ttys must always be in
* minor device number order - the first line should be for tty0, the
* second for tty1, and so on.
*
* Example /etc/tty file (the text following # should not be in /etc/ttys)
* 1c0 # /dev/tty0 is enabled as 1200 baud, no parity
* 2c1 # /dev/tty1 is enabled using /etc/getty for speed detection
* 0c2 # /dev/tty2 is disabled
*
* If any of the /etc/tty entries start with a 2, the file /etc/getty must
* be present and executable.
*
* If the files /usr/adm/wtmp and /etc/utmp exist and are writable, init
* (with help from login) will maintain login accounting. Sending a
* signal 1 (SIGHUP) to init will cause it to reread /etc/ttys and start
* up new shell processes if necessary. It will not, however, kill off
* login processes for lines that have been turned off; do this manually.
*/
#include <sys/types.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <sgtty.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <utmp.h>
#define CONSNAME "/dev/tty0" /* system console device */
#define SHELL1 "/bin/sh"
#define SHELL2 "/usr/bin/sh"
#define LOGIN1 "/bin/login"
#define LOGIN2 "/usr/bin/login"
#define GETTY "/etc/getty" /* GETTY for dial IN/OUT */
#define PIDSLOTS 8 /* maximum number of ttys entries */
#define TTYSBUF (8 * PIDSLOTS) /* buffer for reading /etc/ttys */
#define STACKSIZE (192 * sizeof(char *)) /* init's stack */
#define EXIT_TTYFAIL 253 /* child had problems with tty */
#define EXIT_EXECFAIL 254 /* child couldn't exec something */
#define EXIT_OPENFAIL 255 /* child couldn't open something */
struct uart {
int baud;
int flags;
} uart[] = {
B110, BITS8, /* 'a': 110 baud, 8 bits, no parity */
B300, BITS8, /* 'b': 300 baud, 8 bits, no parity */
B1200, BITS8, /* 'c': 1200 baud, 8 bits, no parity */
B2400, BITS8, /* 'd': 2400 baud, 8 bits, no parity */
B4800, BITS8, /* 'e': 4800 baud, 8 bits, no parity */
B9600, BITS8, /* 'f': 9600 baud, 8 bits, no parity */
B110, BITS7 | EVENP, /* 'g': 110 baud, 7 bits, even parity */
B300, BITS7 | EVENP, /* 'h': 300 baud, 7 bits, even parity */
B1200, BITS7 | EVENP, /* 'i': 1200 baud, 7 bits, even parity */
B2400, BITS7 | EVENP, /* 'j': 2400 baud, 7 bits, even parity */
B4800, BITS7 | EVENP, /* 'k': 4800 baud, 7 bits, even parity */
B9600, BITS7 | EVENP, /* 'l': 9600 baud, 7 bits, even parity */
B110, BITS7 | ODDP, /* 'm': 110 baud, 7 bits, odd parity */
B300, BITS7 | ODDP, /* 'n': 300 baud, 7 bits, odd parity */
B1200, BITS7 | ODDP, /* 'o': 1200 baud, 7 bits, odd parity */
B2400, BITS7 | ODDP, /* 'p': 2400 baud, 7 bits, odd parity */
B4800, BITS7 | ODDP, /* 'q': 4800 baud, 7 bits, odd parity */
B9600, BITS7 | ODDP /* 'r': 9600 baud, 7 bits, odd parity */
};
#define NPARAMSETS (sizeof uart / sizeof(struct uart))
struct slotent {
int onflag; /* should this ttyslot be on? */
int pid; /* pid of login process for this tty line */
int exit; /* eit status of child */
char name[8]; /* name of this tty */
int flags; /* sg_flags field for this tty */
int speed; /* sg_ispeed for this tty */
};
struct slotent slots[PIDSLOTS]; /* init table of ttys and pids */
char stack[STACKSIZE]; /* init's stack */
char *stackpt = &stack[STACKSIZE];
char **environ; /* declaration required by library routines */
extern int errno;
char *CONSOLE = CONSNAME; /* name of system console */
struct sgttyb args; /* buffer for TIOCGETP */
int gothup = 0; /* flag, showing signal 1 was recieved */
int pidct = 0; /* count of running children */
char *env[] = { (char *)0 }; /* tiny environment for execle */
main()
{
int pid; /* pid of child process */
int fd; /* fd of console for error messages */
int i; /* loop variable */
int status; /* return status from child process */
struct slotent *slotp; /* slots[] pointer */
void onhup(); /* SIGHUP interrupt catch routine */
sync(); /* force buffers out onto disk */
/* Execute the /etc/rc file. */
if(fork()) {
/* Parent just waits. */
wait(&status);
} else {
/* Child exec's the shell to do the work. */
if(open("/etc/rc", 0) < 0) exit(EXIT_OPENFAIL);
dup(open(CONSOLE, 1)); /* std output, error */
execle(SHELL1, SHELL1, (char *)0, env);
execle(SHELL2, SHELL2, (char *)0, env);
exit(EXIT_EXECFAIL); /* impossible, we hope */
}
/* Log system reboot. */
wtmp("reboot", "~~", "~", 0, BOOT_TIME, -1);
/* Read the /etc/ttys file. */
readttys();
/* Main loop. If login processes have already been started up, wait for one
* to terminate, or for a HUP signal to arrive. Start up new login processes
* for all ttys which don't have them. Note that wait() also returns when
* somebody's orphan dies, in which case ignore it.
* First set up the signals.
*/
for (i = 1; i <= _NSIG; i++) signal(i, SIG_IGN);
signal(SIGHUP, onhup);
while(1) {
sync();
if( pidct && (pid = wait(&status)) > 0 ) {
/* Search to see which line terminated. */
for(slotp = slots; slotp < &slots[PIDSLOTS]; ++slotp) {
if(slotp->pid == pid) {
pidct--;
slotp->pid = 0; /* now no login process */
slotp->exit = status;
if(((status >> 8) & 0xFF) == EXIT_TTYFAIL) {
fd = open(CONSOLE, 1);
write(fd, "init: tty problems, shutting down ", 39);
write(fd, slotp->name, sizeof slotp->name);
write(fd, "\n", 1);
close(fd);
slotp->onflag = 0;
}
break;
}
}
}
/* If a signal 1 (SIGHUP) is received, reread /etc/ttys. */
if(gothup) {
readttys();
gothup = 0;
}
/* See which lines need a login process started up. */
for(slotp = slots; slotp < &slots[PIDSLOTS]; ++slotp) {
if(slotp->onflag && slotp->pid <= 0)
startup(slotp - slots, DEAD_PROCESS, LOGIN_PROCESS);
}
}
}
void onhup()
{
gothup = 1;
signal(SIGHUP, onhup);
}
readttys()
{
/* (Re)read /etc/ttys. */
char ttys[TTYSBUF]; /* buffer for reading /etc/ttys */
register char *p; /* current pos. within ttys */
char *endp; /* pointer to end of ttys buffer */
int fd; /* file descriptor for /etc/ttys */
struct slotent *slotp = slots; /* entry in slots[] */
char *q; /* pointer for copying ttyname */
if((fd = open("/etc/ttys", 0)) < 0) {
write(open(CONSOLE, 1), "init: can't open /etc/ttys\n", 27);
while (1) ; /* just hang -- system cannot be started */
}
/* Read /etc/ttys file. */
endp = (p = ttys) + read(fd, ttys, TTYSBUF);
*endp = '\n';
/* The first character of each line on /etc/ttys tells what to do:
* 0 = do not enable line
* 1 = enable line for regular login
* 2 = use /etc/getty on this line to detect modem speed dynamically
*/
while(p < endp) {
switch(*p++) {
case '0': /* no getty/login */
slotp->onflag = 0;
break;
case '1': /* use login on this line */
slotp->onflag = 1;
break;
case '2': /* use GETTY on this line */
slotp->onflag = 2;
break;
default:
/* First char of line is rotten. Skip this entry. */
while(*p++ != '\n') ; /* read until '\n' hit */
continue; /* go to next entry */
}
slotp->exit = 0;
slotp->flags = CRMOD | XTABS | ECHO; /* sg_flags setting */
/* Now examine the second cha